using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Threading;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net;
using System.IO;

namespace NetMonitor
{
    public partial class PingerComponent : UserControl
    {
      
        bool running = false;

        private Thread pingThread;
        List<int> history;

        // Public Properties, can be accessed in Property Panel
        //public enum PingType { Ping, infoPing_CPU, infoPing_MEM };

        string mPingType;
        public string pingType
        {
            get { return mPingType; }
            set { mPingType = value; }
        }

        string mHostname;
        public string hostname
        {
            get { return mHostname; }
            set { mHostname = value; }
        }

        string mAlias;
        public string alias
        {
            get { return mAlias; }
            set { mAlias = value; }
        }

        int mPort;
        public int port
        {
            get { return mPort; }
            set { mPort = value; }
        }

        int mPingMax;
        public int pingMax
        {
            get { return mPingMax; }
            set { mPingMax = value; }
        }

        int mPingTimeOut;
        public int pingTimeOut
        {
            get { return mPingTimeOut; }
            set { mPingTimeOut = value; }
        }

        int mPingInterval;
        public int pingInterval
        {
            get { return mPingInterval; }
            set { mPingInterval = value; }
        }


        int mHistorySize;
        public int historySize
        {
            get { return mHistorySize; }
            set { mHistorySize = value; }
        }





        public PingerComponent()
        {
            history = new List<int>();
            CheckForIllegalCrossThreadCalls = false;
            pingMax = 900;
            historySize = 64;
            pingTimeOut = 1900;
            pingInterval = 4000;
            alias = "";
            add(1);
            InitializeComponent();
        }


        public void start()
        {
            if (pingThread == null || !pingThread.IsAlive)
            {
                pingThread = new Thread(new ThreadStart(pingerThreadFunc));
                running = true;
                pingThread.Start();
                buttonPlayStop.Text = ">";
            }
        }

        

        public void stop()
        {
            if (pingThread != null)
            {
                running = false;
                buttonPlayStop.Text = "||";
            }
        }

        protected void pingerThreadFunc()
        {
            try
            {
                Ping ping = new Ping();
                bool running2 = false;
                this.Invoke((MethodInvoker)delegate
                        {
                            running2 = running;
                        });
            
                string hostname = "";
                this.Invoke((MethodInvoker)delegate
                    {
                        hostname = mHostname;
                    });

                try
                {
                    int iReply = -1;
                    string sReply;
                    switch (mPingType)
                    {
                        case "PING":
                            PingReply reply = ping.Send(hostname, pingTimeOut);
                            iReply = (int)reply.RoundtripTime;
                            break;
                        case "FILE":
                            string filename = "test6.txt";
                            sReply = infoPing(hostname, "FILE" + 
                                Encoding.ASCII.GetString(BitConverter.GetBytes((ulong)(filename.Length))) + filename + "asdl;kfja;ksdjf;lkj", mPort);
                            break;    
                        //int.TryParse(sReply, out iReply);
                        default:
                            sReply = infoPing(hostname, mPingType, mPort);
                            int.TryParse(sReply, out iReply);
                            break;
                    }

                    this.Invoke((MethodInvoker)delegate
                    {
                        add(iReply);
                    });
                }
                catch (Exception ex)
                {
                    add(-1);
                    ex.ToString();
                }
                pictureBox1.Invoke((MethodInvoker)delegate
                    {
                        pictureBox1.Refresh();
                    });

                buttonPlayStop.Invoke((MethodInvoker)delegate
                    {
                        buttonPlayStop.BackColor = Color.Blue;
                    });
                Thread.Sleep(200);
                buttonPlayStop.Invoke((MethodInvoker)delegate
                   {
                       buttonPlayStop.BackColor = Color.Silver;
                   });
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
            this.Refresh();
        }

        /*protected void pingerThreadFunc()
        {
            try
            {
               // bool error;
                Ping ping = new Ping();
                bool running2 = false;
                this.Invoke((MethodInvoker)delegate
                        {
                           running2 = running;
                        });
                while (running2)
                {
                   // error = false;
                    string hostname = "";
                    this.Invoke((MethodInvoker)delegate
                        {
                            hostname = mHostname;
                        });

                    try
                    {
                        int iReply = -1;
                        switch (mPingType)
                        {
                            case PingType.Ping:
                                PingReply reply = ping.Send(hostname, pingTimeOut);
                                iReply = (int)reply.RoundtripTime;
                                break;
                            case PingType.infoPing_CPU:
                                string sReply = infoPing(hostname, "CPU", mPort);
                                int.TryParse(sReply, out iReply);
                                break;

                        }
                        

                        this.Invoke((MethodInvoker)delegate
                        {
                            add(iReply);
                        });
                    }
                    catch (Exception ex)
                    {
                        add(-1);
                        //error = true;
                        ex.ToString();
                    }
                    pictureBox1.Invoke((MethodInvoker)delegate
                        {
                            pictureBox1.Refresh();
                        });

                    buttonPlayStop.Invoke((MethodInvoker)delegate
                        {
                            buttonPlayStop.BackColor = Color.Blue;
                        });
                    Thread.Sleep(200);
                    buttonPlayStop.Invoke((MethodInvoker)delegate
                       {
                           buttonPlayStop.BackColor = Color.Silver;
                       });
                    Thread.Sleep(pingInterval);
                    this.Invoke((MethodInvoker)delegate
                        {
                            running2 = running;
                        });
                }
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
        }*/

        protected string infoPing(String server, String message, Int32 port)
        {
            Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
            Byte[] reply = new Byte[512];
            try
            {
                TcpClient client = new TcpClient(server, port);
                if (!client.Connected)
                    return "-3";
                client.Client.Send(data, SocketFlags.None);
                if (client.Client.Receive(reply, SocketFlags.None) <= 0)
                    return "-4";


                client.Close();
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException: {0}", e);
                return "-1";
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
                return "-2";
            }
            return Encoding.ASCII.GetString(reply);
        }


        private void add(int reply)
        {
            if (reply < 0 || reply > pingMax)
                warningNoise();
            history.Add(reply);
            if (history.Count > historySize)
                history.RemoveAt(0);
        }

        static void warningNoise()
        {
            Console.Beep(1000,200);
            Console.Beep(1370, 200);
        }

        public int status()
        {
            int ret = 0;
            // go through history and see if any bad results and if there are make it orange.
            for (int i = 0; i < history.Count - 1; i++)
            {
                if ((history[i] <= -1) || history[i] >= pingMax)
                    ret = 1;
            }
            if (history.Count > 1 && (history[history.Count - 1] <= -1) || history[history.Count - 1] >= pingMax)
                ret = 2;
            return ret;
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            int w = pictureBox1.Width, h = pictureBox1.Height;
            Brush backColor = Brushes.LimeGreen;          
            switch (status())
            {
                case 1: backColor = Brushes.Orange;
                    break;
                case 2: backColor = Brushes.Red;
                    break;
            }

            g.FillRectangle(backColor, 0, 0, w, h);

            for (int i = 0; i < history.Count - 1; i++)
            {
                Pen pen = new Pen(Color.Black, 2);
                if (history[i + 1] >= 0 && history[i] >= 0)
                    g.DrawLine(pen,
                        (i * w / historySize), calcY(history[i]),
                        ((i + 1) * w / historySize), calcY(history[i+1]) );
            }

            //Brush b = new SolidBrush((Color.FromArgb(170, Color.White)));
            //g.FillRectangle(b,0,0,pictureBox1.Width,35);
            if (alias == "")
                labelAlias.Text = hostname;
            //g.DrawString(hostname, new Font("Tahoma", 16), Brushes.Black, new PointF(5, 5));
            else
                labelAlias.Text = alias;
                //g.DrawString(alias, new Font("Tahoma", 16), Brushes.Black, new PointF(5, 5));
            labelLast.Text = history[history.Count - 1].ToString();
            //g.DrawString(history[history.Count - 1].ToString(), new Font("Tahoma", 10), Brushes.Black, new PointF(pictureBox1.Width - 34, 20));
        }

        private int calcY(int _val)
        {            
            int  h = pictureBox1.Height;
            if (_val > pingMax)
                return 1;
            return h - (_val * h) / pingMax - 1;
        }

        private void buttonPlayStop_Click(object sender, EventArgs e)
        {
            if (buttonPlayStop.Text == ">")
            {
                stop();
            }
            else
            {
                start();
            }
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {
            
        /*    ThingProperties pp = new ThingProperties(this);
            
            if (pp.ShowDialog() == DialogResult.OK)
            {
                this.pingInterval = pp.interval;
                this.pingMax = pp.max;
                this.pingTimeOut = pp.timeOut;
                this.pingType = pp.type;
                this.alias = pp.alias;
                this.historySize = pp.historySize;
                hostname = pp.hostname;
            }*/
            
        }

        

    


    }
}
